﻿using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
using RestSharp;
using sixgod.Common.Extension;
using sixgod.Common.Model;

namespace sixgod.personnel.AuthenticationHandler;

/// <summary>
/// 单点登录中心认证
/// </summary>
public class SsoAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
    public const string CustomerSchemeName = "SsoAuth";

    private IConfiguration _configuration;

    /// <summary>
    /// Initializes a new instance of <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationHandler`1" />.
    /// </summary>
    /// <param name="options">The monitor for the options instance.</param>
    /// <param name="logger">The <see cref="T:Microsoft.Extensions.Logging.ILoggerFactory" />.</param>
    /// <param name="encoder">The <see cref="T:System.Text.Encodings.Web.UrlEncoder" />.</param>
    /// <param name="clock">The <see cref="T:Microsoft.AspNetCore.Authentication.ISystemClock" />.</param>
    public SsoAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IConfiguration configuration) : base(options, logger, encoder, clock)
    {
        _configuration = configuration;
        
    }

    /// <summary>Allows derived types to handle authentication.</summary>
    /// <returns>The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticateResult" />.</returns>
    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        if (!Request.Headers.ContainsKey("access_token"))
        {
            return AuthenticateResult.Fail("未登录");
        }

        var token = Request.Headers["access_token"];
        if (string.IsNullOrEmpty(token))
        {
            return AuthenticateResult.Fail("令牌为空");
        }

        var client = new RestClient(_configuration["SSO:Url"]);
        var request = new RestRequest("/SSO/auth/" + token);

        try
        {
            var res = await client.GetAsync(request);
            if (!res.IsSuccessful)
            {
                return AuthenticateResult.Fail(res.ErrorMessage);
            }

            var data = res.Content!.ToObj<ResponseResult<string>>();
            if (data.Code == StatusCode.Success)
            {
                var handler = new JwtSecurityTokenHandler();
                var t = handler.ReadJwtToken(token);
                var identity = new ClaimsIdentity(t.Claims, "Bearer");
                var principal = new ClaimsPrincipal(identity);
                var ticket = new AuthenticationTicket(principal, Scheme.Name);
                return AuthenticateResult.Success(ticket);
            }

            else
            {
                if (data.Code == StatusCode.Fail)
                {
                    return AuthenticateResult.Fail("令牌错误");
                }
                else if (data.Code == StatusCode.OutTime)
                {
                    return AuthenticateResult.Fail("令牌超时");
                }
                else
                {
                    return AuthenticateResult.Fail(data.Msg);
                }
            }
        }
        catch
        {
            return AuthenticateResult.Fail("sso远程认证出错");
        }
    }
    
}